﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Design.Serialization;
using System.ComponentModel;
using System.CodeDom;
using System.Reflection;
using ProgNetComponents.Serialization;

namespace ProgNetComponents.Design.Serialization
{
    public class ConstantSerializer : CodeDomSerializer
    {
        public ConstantSerializer()
            : base()
        {
            this.
        }
        public override object Serialize(IDesignerSerializationManager manager, object value)
        {
            "public override object Serialize(IDesignerSerializationManager manager, object value)".Log();
            try
            {
                CodeDomSerializer baseSerializer = (CodeDomSerializer)manager.GetSerializer(
                 typeof(Component), typeof(CodeDomSerializer));
                if (baseSerializer != null)
                {
                    object codeObject = baseSerializer.Serialize(manager, value);
                    CodeStatementCollection statements = (CodeStatementCollection)codeObject;
                    foreach (CodeObject o in statements)
                    {
                        if (o is CodeAssignStatement)
                        {
                            CodeAssignStatement a = o as CodeAssignStatement;
                            if ((a.Left is CodePropertyReferenceExpression))
                            {
                                try
                                {
                                    string editorTypeName = "";
                                    Type ConstantClass = null;
                                    if (value != null)
                                    {
                                        PropertyInfo pi = value.GetType().GetSingleProperty((a.Left as CodePropertyReferenceExpression).PropertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy);
                                        if (pi != null && pi.PropertyType == typeof(string))
                                        {
                                            object[] attributes = pi.GetCustomAttributes(true);
                                            if (attributes != null)
                                            {
                                                foreach (object att in attributes)
                                                {
                                                    if (att is EditorAttribute)
                                                    {
                                                        editorTypeName = (att as EditorAttribute).EditorTypeName;
                                                    }
                                                    
                                                    if (editorTypeName.IsNotNull())
                                                        break;
                                                }
                                            }
                                            if (editorTypeName.IsNotNull() && (a.Right is CodePrimitiveExpression))
                                            {
                                                Type t = null;
                                                t = manager.GetType(editorTypeName);
                                                if (t == null)
                                                    t = manager.GetType(editorTypeName, null);
                                                if(t == null)
                                                    t = editorTypeName.GetAssemblyType();
                                                
                                                if (t != null)
                                                {
                                                    PropertyInfo p = t.GetSingleProperty("ConstantClass");
                                                    if (p != null)
                                                    {
                                                        object inst = Activator.CreateInstance(t);
                                                        ConstantClass = p.GetValue(inst, null) as Type;
                                                    }
                                                }
                                            }
                                            
                                            if (ConstantClass != null)
                                            {
                                                string val = (a.Right as CodePrimitiveExpression).Value.AsString();
                                                if (val.IsNotNull())
                                                    a.Right = new CodeSnippetExpression(ConstantClass.FullName + "." + ProjectHelper.GetName(val));
                                                else
                                                {
                                                    "   a.Right = new CodeSnippetExpression(null);".Log();
                                                    a.Right.AsString().Log();
                                                    (a.Right as CodePrimitiveExpression).Value.AsString().Log();
                                                    a.Right = new CodeSnippetExpression("null");
                                                }
                                            }
                                        }
                                    }
                                }
                                catch { }
                            }
                        }
                    }
                    return statements;
                }
            }
            catch { }
            return new CodeStatementCollection();
        }
        public override object Deserialize(IDesignerSerializationManager manager, object codeObject)
        {
            "public override object Deserialize(IDesignerSerializationManager manager, object codeObject)".Log();
            return base.Deserialize(manager, codeObject);
        }
        protected override object DeserializeInstance(IDesignerSerializationManager manager, Type type, object[] parameters, string name, bool addToContainer)
        {
            "protected override object DeserializeInstance(IDesignerSerializationManager manager, Type type, object[] parameters, string name, bool addToContainer)".Log();
            return base.DeserializeInstance(manager, type, parameters, name, addToContainer);
        }
        public override string GetTargetComponentName(CodeStatement statement, CodeExpression expression, Type targetType)
        {
            "public override string GetTargetComponentName(CodeStatement statement, CodeExpression expression, Type targetType)".Log();
            return base.GetTargetComponentName(statement, expression, targetType);
        }
        public override object SerializeAbsolute(IDesignerSerializationManager manager, object value)
        {
            "public override object SerializeAbsolute(IDesignerSerializationManager manager, object value)".Log();
            return base.SerializeAbsolute(manager, value);
        }
        public override CodeStatementCollection SerializeMember(IDesignerSerializationManager manager, object owningObject, MemberDescriptor member)
        {
            "public override CodeStatementCollection SerializeMember(IDesignerSerializationManager manager, object owningObject, MemberDescriptor member)".Log();
            return base.SerializeMember(manager, owningObject, member);
        }
        public override CodeStatementCollection SerializeMemberAbsolute(IDesignerSerializationManager manager, object owningObject, MemberDescriptor member)
        {
            "public override CodeStatementCollection SerializeMemberAbsolute(IDesignerSerializationManager manager, object owningObject, MemberDescriptor member)".Log();
            return base.SerializeMemberAbsolute(manager, owningObject, member);
        }
    }
}
